package com.ccx.demo.business.common.controller;

import com.alibaba.fastjson.JSON;
import com.ccx.demo.business.user.entity.TabUser;
import com.ccx.demo.config.init.AppConfig;
import com.ccx.demo.config.init.AppConfig.Path;
import com.ccx.demo.config.init.AppConfig.URL;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.support.mvc.entity.base.Item;
import com.support.mvc.entity.base.Result;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.context.ApplicationContext;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 参数配置
 *
 * @author 谢长春 2017年7月21日 上午10:19:28
 */
@Controller
@Secured("ROLE_ADMIN")
@RequestMapping("/admin-config")
@Slf4j
@RequiredArgsConstructor
public class AdminConfigController {
    private final ApplicationContext applicationContext;
    private final ExecutorService multiThread;
    private final CacheManager cacheManager;
    private final AppConfig appConfig;

    @ApiIgnore
    @GetMapping("/system")
    @ApiOperation(value = "2.系统环境变量", tags = {"0.0.0"})
    @ApiOperationSupport(order = 2, author = "谢长春")
    @ResponseBody
    public Result<SortedMap<String, Object>> system() {
        return new Result<SortedMap<String, Object>>().execute(result -> {
            final Properties properties = System.getProperties();
            final SortedMap<String, Object> map = new TreeMap<>();
            properties.forEach((key, value) -> map.put(Objects.toString(key), value));
            result.setSuccess(map);
        });
    }

    @GetMapping("/app")
    @ResponseBody
    public Result<AppConfig> getApp(@ApiIgnore @AuthenticationPrincipal final TabUser user) {
        return new Result<AppConfig>().execute(result -> result.setSuccess(appConfig));
    }

    @GetMapping("/path")
    @ResponseBody
    public Result<Item> getPath(@ApiIgnore @AuthenticationPrincipal final TabUser user) {
        return new Result<Item>().execute(result -> result
                .setSuccess(Stream.of(Path.values())
                        .map(key -> Item.builder().key(key.name()).value(key.get()).comment(key.comment).build())
                        .collect(Collectors.toList())
                )
        );
    }

    @GetMapping("/url")
    @ResponseBody
    public Result<Item> getUrl(@ApiIgnore @AuthenticationPrincipal final TabUser user) {
        return new Result<Item>().execute(result -> result
                .setSuccess(Stream.of(URL.values())
                        .map(key -> Item.builder().key(key.name()).value(key.value()).comment(key.comment).build())
                        .collect(Collectors.toList())
                )
        );
    }

    @GetMapping("/cache/string/{name}/{key}")
    @ResponseBody
    public Result<Object> getCacheString(
            @ApiIgnore @AuthenticationPrincipal final TabUser user,
            @PathVariable String name,
            @PathVariable String key) {
        return new Result<>().execute(result -> {
            final Optional<Object> optional = Optional.ofNullable(cacheManager.getCache(name))
                    .map(cache -> cache.get(key))
                    .map(Cache.ValueWrapper::get);
            try {
                result.setSuccess(optional.map(JSON::toJSONString).map(JSON::parseObject).orElse(null));
            } catch (Exception e) {
                result.setSuccess(optional.orElse(null));
            }
        });
    }

    @GetMapping("/cache/long/{name}/{key}")
    @ResponseBody
    public Result<Object> getCacheLong(
            @ApiIgnore @AuthenticationPrincipal final TabUser user,
            @PathVariable String name,
            @PathVariable Long key) {
        return new Result<>().execute(result -> {
            final Optional<Object> optional = Optional.ofNullable(cacheManager.getCache(name))
                    .map(cache -> cache.get(key))
                    .map(Cache.ValueWrapper::get);
            try {
                result.setSuccess(optional.map(JSON::toJSONString).map(JSON::parseObject).orElse(null));
            } catch (Exception e) {
                result.setSuccess(optional.orElse(null));
            }
        });
    }

    @DeleteMapping("/cache/clear/{name}")
    @ResponseBody
    public Result<Object> cacheClear(
            @ApiIgnore @AuthenticationPrincipal final TabUser user,
            @PathVariable String name) {
        return new Result<>().call(() -> Optional.ofNullable(cacheManager.getCache(name)).ifPresent(Cache::clear));
    }

    @DeleteMapping("/cache/clear/string/{name}/{key}")
    @ResponseBody
    public Result<Object> cacheClear(
            @ApiIgnore @AuthenticationPrincipal final TabUser user,
            @PathVariable String name,
            @PathVariable String key) {
        return new Result<>().call(() -> Optional.ofNullable(cacheManager.getCache(name)).ifPresent(cache -> cache.evict(key)));
    }

    @DeleteMapping("/cache/clear/long/{name}/{key}")
    @ResponseBody
    public Result<Object> cacheClear(
            @ApiIgnore @AuthenticationPrincipal final TabUser user,
            @PathVariable String name,
            @PathVariable Long key) {
        return new Result<>().call(() -> Optional.ofNullable(cacheManager.getCache(name)).ifPresent(cache -> cache.evict(key)));
    }


//    @PostMapping(value = "/api/encrypt", produces = "text/plain", consumes = "text/plain")
//    @ResponseBody
//    public String apiAesEncrypt(
//            @ApiIgnore @AuthenticationPrincipal final TabUser user,
//            @RequestBody final String body) {
//        return AesApi.encrypt(body);
//    }
//
//    @PostMapping(value = "/api/decrypt", produces = "text/plain", consumes = "text/plain")
//    @ResponseBody
//    public String apiAesDecrypt(
//            @ApiIgnore @AuthenticationPrincipal final TabUser user,
//            @RequestBody final String body) {
//        return AesApi.decrypt(body);
//    }
}
